package avicit.bdp.dms.prm.service;

import avicit.bdp.common.base.BaseService;
import avicit.bdp.common.utils.BdpLogUtil;
import avicit.bdp.common.utils.enums.CommonTypeEnums;
import avicit.bdp.common.utils.enums.CommonTypeLeaf;
import avicit.bdp.common.utils.enums.FileCategory;
import avicit.bdp.core.constant.Constants;
import avicit.bdp.dds.dispatch.enums.ReleaseState;
import avicit.bdp.dms.prm.dao.TagDAO;
import avicit.bdp.dms.prm.dto.TagDTO;
import avicit.platform6.commons.utils.ComUtil;
import avicit.platform6.core.context.ThreadContextHelper;
import avicit.platform6.core.exception.BusinessException;
import avicit.platform6.core.exception.BusinessException;
import avicit.platform6.core.properties.PlatformConstant;
import avicit.platform6.core.rest.msg.QueryRespBean;
import com.alibaba.fastjson2.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 标签表服务
 */
@Transactional
@Service
public class TagService extends BaseService<TagDAO, TagDTO> {

    public static final Integer DEFAULT_ORDER_BY = 0;

    /**
     * 新增标签
     *
     * @return java.lang.String
     * @param    tag
     * @author felix
     * @date 2021/3/29 16:52
     */
    @Transactional(rollbackFor = Exception.class)
    public String insertTag(TagDTO tag) {
        try {
            tag.setId(ComUtil.getId());
            if (tag.getOrderBy() == null) {
                tag.setOrderBy(DEFAULT_ORDER_BY);
            }
            insertSelective(tag);
            //记录日志
            BdpLogUtil.log4Insert(tag);
            return tag.getId();
        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    /**
     * 修改标签/分类接口
     *
     * @param    tag
     * @author felix
     * @date 2021/3/31 11:24
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateTag(TagDTO tag) {
        try {
            updateByPrimaryKey(getTag(tag));
        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    private TagDTO getTag(TagDTO tag) {
        TagDTO oldDTO = selectByPrimaryKey(tag.getId());
        if (oldDTO == null) {
            throw new BusinessException("数据不存在");
        }
        if(tag.getCategory()==1) {
            if (oldDTO.getLeaf() == 0 && tag.getLeaf() == 1) {
                TagDTO query = new TagDTO();
                query.setParentId(oldDTO.getId());
                if (selectCount(query) > 0) {
                    throw new BusinessException("修改失败！该节点下存在子节点，不可改为末级节点 ");
                }
            }
            if (oldDTO.getLeaf() == 1 && tag.getLeaf() == 0) {
                TagDTO query = new TagDTO();
                query.setParentId(oldDTO.getId());
                if (selectCount(query) > 0) {
                    throw new BusinessException("修改失败！该节点已关联数据，不可改为非末级节点");
                }
            }
        }
        //记录日志
        BdpLogUtil.log4Update(tag, oldDTO);

        oldDTO.setName(tag.getName());
        oldDTO.setOrderBy(tag.getOrderBy());
        oldDTO.setRemark(tag.getRemark());
        if (oldDTO.getCategory() == FileCategory.CATEGORY.getCode()) {//如果是分类
            oldDTO.setLeaf(tag.getLeaf());
            oldDTO.setUnfolded(tag.getUnfolded());
        } else {//如果是标签
            oldDTO.setCode(tag.getCode());
            oldDTO.setTagType(tag.getTagType());
            oldDTO.setTagStatus(tag.getTagStatus());
        }
        return oldDTO;
    }

    /**
     * 删除标签接口
     *
     * @author felix
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteTag(String id) {
        if (StringUtils.isBlank(id)) {
            throw new BusinessException("删除失败！传入的参数主键为null");
        }
        try {
            //记录日志
            TagDTO tag = selectByPrimaryKey(id);
            if (tag == null) {
                throw new BusinessException("删除失败！对象不存在");
            }
            if (tag.getCategory() == FileCategory.FILE.getCode() && tag.getTagStatus() == ReleaseState.ONLINE.getCode()) {
                throw new BusinessException("删除失败！启用状态下不可删除");
            }
            if (tag.getCategory() == FileCategory.CATEGORY.getCode() && checkChild(tag.getId())) {
                throw new BusinessException("删除失败！该分类存在子节点");
            }
            BdpLogUtil.log4Delete(tag);
            //删除业务数据
            deleteByPrimaryKey(id);
        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    private boolean checkChild(String id) {
        boolean flag = false;
        TagDTO tagDTO = new TagDTO();
        tagDTO.setParentId(id);
        List<TagDTO> list = this.selectList(tagDTO);
        if (list != null && list.size() > 0) {
            flag = true;
        }
        return flag;
    }

    /**
     * 批量修改状态接口
     *
     * @param    ids
     * @param    status
     * @author felix
     * @date 2021/3/30 9:23
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateTagStatue(String ids, Integer status) {
        if (StringUtils.isAnyBlank(ids, status.toString())) {
            throw new BusinessException("请检查参数!");
        }
        try {
            String[] idArray = ids.split(Constants.COMMA);
            for (String tagId : idArray) {
                TagDTO tagDto = selectByPrimaryKey(tagId);
                tagDto.setTagStatus(status);
                updateByPrimaryKeySelective(tagDto);
                //记录日志
                String logTitle = "";
                if(status == 1){
                    logTitle = "启用标签：【";
                }else {
                    logTitle = "停用标签：【";
                }
                logTitle += tagDto.getName()+"】";
                BdpLogUtil.log("标签管理模块",logTitle, PlatformConstant.OpType.update);
            }
        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    /**
     * 批量移动接口
     *
     * @return void
     * @param    ids
     * @param    parentId
     * @author felix
     * @date 2021/3/30 9:24
     */
    @Transactional(rollbackFor = Exception.class)
    public void moveTag(String ids, String parentId) {
        if (StringUtils.isAnyBlank(ids, parentId)) {
            throw new BusinessException("请检查参数!");
        }
        try {
            String[] idArray = ids.split(Constants.COMMA);
            for (String tagId : idArray) {
                TagDTO tagDto = new TagDTO();
                tagDto.setId(tagId);
                tagDto.setParentId(parentId);
                updateByPrimaryKeySelective(tagDto);
            }

            String logTitle = "移动服务标签：【" + JSONObject.toJSONString(idArray) + "】";
            BdpLogUtil.log("服务标签模块", logTitle, PlatformConstant.OpType.update);
        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    /**
     * 根据分类ID查询标签接口
     *
     * @param    categoryId
     * @param    keyWords
     * @param    pageNo
     * @param    pageSize
     * @author felix
     * @date 2021/3/30 10:09
     */
    @Transactional(readOnly = true)
    public QueryRespBean<TagDTO> findTags(String categoryId, String keyWords, Integer pageNo,
                                          Integer pageSize) {
        QueryRespBean<TagDTO> queryRespBean = new QueryRespBean<>();
        try {
            List<String> categoryIds = getChildrenIds(categoryId);
            categoryIds.add(categoryId);

            // 文档密级
            List<String> wordSecretList = ThreadContextHelper.getWordSecretList();
            PageHelper.startPage(pageNo, pageSize);
            Page<TagDTO> dataList = this.mapper.getList(categoryIds, keyWords, wordSecretList);
            queryRespBean.setResult(dataList);
            BdpLogUtil.log4Query(queryRespBean);
            return queryRespBean;
        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    private List<String> getChildrenIds(String categoryId) {
        List<String> list = Lists.newArrayList();
        Map<String, List<TagDTO>> map = Maps.newHashMap();
        TagDTO tagDTO = new TagDTO();
        tagDTO.setCategory(FileCategory.CATEGORY.getCode());
        List<TagDTO> categoryList = selectList(tagDTO);
        if (CollectionUtils.isNotEmpty(categoryList)) {
            for (TagDTO category : categoryList) {
                if (map.containsKey(category.getParentId())) {
                    List<TagDTO> tagDTOList = map.get(category.getParentId());
                    tagDTOList.add(category);
                } else {
                    List<TagDTO> tagDTOList = Lists.newArrayList();
                    tagDTOList.add(category);
                    map.put(category.getParentId(), tagDTOList);
                }
            }
        }
        categoryIdsConvert(categoryId, map, list);
        return list;
    }

    private void categoryIdsConvert(String categoryId, Map<String, List<TagDTO>> map, List<String> list) {
        List<TagDTO> commonTypeList = map.get(categoryId);
        if (commonTypeList != null && commonTypeList.size() > 0) {
            for (TagDTO commonTypeDTO : commonTypeList) {
                if (commonTypeDTO.getLeaf() == CommonTypeLeaf.LEAF.getCode()) {
                    list.add(commonTypeDTO.getId());
                } else {
                    categoryIdsConvert(commonTypeDTO.getId(), map, list);
                }
            }
        }
    }

    /**
     * 查询左侧分类树接口
     *
     * @author felix
     */
    @Transactional(readOnly = true)
    public List<TagDTO> findTagCategory(Integer cite, String secretLevel) {
        // 文档密级
        List<String> wordSecretList = new ArrayList<>();
        if(StringUtils.isNotEmpty(secretLevel)){
            wordSecretList.add(secretLevel);
        }

        try {
            // 顶级节点
            List<TagDTO> list = Lists.newArrayList();
            // 子节点数据
            Map<String, List<TagDTO>> map = Maps.newHashMap();
            TagDTO tagDTO = new TagDTO();
            List<TagDTO> dataList;

            if (cite == FileCategory.CATEGORY.getCode()) {
                tagDTO.setCategory(FileCategory.CATEGORY.getCode());
                dataList = selectList(tagDTO)
                        .stream()
                        .sorted(Comparator.comparing(TagDTO::getOrderBy, Comparator.nullsLast(Integer::compareTo)))
                        .collect(Collectors.toList());
            } else {
                dataList = this.getCategoryAndTag(wordSecretList);
            }

            if (CollectionUtils.isNotEmpty(dataList)) {
                for (TagDTO tag : dataList) {
                    if (CommonTypeEnums.TOP_TYPE_ID.equals(tag.getParentId())) {
                        list.add(tag);
                    } else {
                        if (map.containsKey(tag.getParentId())) {
                            map.get(tag.getParentId()).add(tag);
                        } else {
                            List<TagDTO> tagList = Lists.newArrayList();
                            tagList.add(tag);
                            map.put(tag.getParentId(), tagList);
                        }
                    }
                }
            }
            listConvert(list, map);
            return list;
        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    private List<TagDTO> getCategoryAndTag(List<String> wordSecretList) {
        return this.mapper.getCategoryAndTag(wordSecretList);
    }

    private void listConvert(List<TagDTO> list, Map<String, List<TagDTO>> map) {
        for (TagDTO tagDTO : list) {
            List<TagDTO> tagList = map.get(tagDTO.getId());
            if (CollectionUtils.isNotEmpty(tagList)) {
                listConvert(tagList, map);
                tagDTO.setChildren(tagList);
            } else {
                tagDTO.setChildren(null);
            }
        }
    }

    /**
     * 判断标签分类名称是否重复
     *
     * @param    id
     * @param    parentId
     * @param    name
     * @author felix
     * @date 2021/3/30 16:37
     */
    public Boolean isSameCategoryName(String id, String parentId, String name) {
        Boolean flag = false;
        if (StringUtils.isAnyBlank(parentId, name)) {
            throw new BusinessException("请检查参数!");
        }
        TagDTO tagDTO = new TagDTO();
        tagDTO.setCategory(FileCategory.CATEGORY.getCode());
        tagDTO.setName(name);
        tagDTO.setParentId(parentId);
        List<TagDTO> list = selectList(tagDTO);
        if (list != null && list.size() > 0) {
            if (StringUtils.isBlank(id)) {
                return true;
            }
            for (TagDTO dto : list) {
                if (!dto.getId().equals(id)) {
                    flag = true;
                    break;
                }
            }
        }
        return flag;
    }

    /**
     * 判断标签名称和code是否重复
     *
     * @param    id
     * @param    value
     * @param    type
     * @author felix
     * @date 2021/3/30 16:41
     */
    public Boolean isSameName(String id, String value, String type) {
        Boolean flag = false;
        if (StringUtils.isAnyBlank(value, type)) {
            throw new BusinessException("请检查参数!");
        }
        TagDTO tagDTO = new TagDTO();
        tagDTO.setCategory(FileCategory.FILE.getCode());
        if ("name".equals(type)) {
            tagDTO.setName(value);
        } else if ("code".equals(type)) {
            tagDTO.setCode(value);
        }
        List<TagDTO> list = selectList(tagDTO);
        if (list != null && list.size() > 0) {
            if (StringUtils.isBlank(id)) {
                return true;
            }
            for (TagDTO dto : list) {
                if (!dto.getId().equals(id)) {
                    flag = true;
                    break;
                }
            }
        }
        return flag;
    }

    public List<String> selectNameByIds(List<String> tagIdList) {
        return this.mapper.selectNameByIds(tagIdList);
    }
}
